﻿using System;
namespace Netduino4Fun.DesktopAssistant.Netduino.Communication
{
    public abstract class Connection
    {
        const int readBufferSize = 1000;
        string readBuffer = string.Empty;

        /// <summary>
        /// Opens the connection.
        /// </summary>
        public abstract void Open();
       
        #region Read
        protected void Read(string data)
        {
            if (data == null)
                return;

            if (data.Length + readBuffer.Length > readBufferSize)
                // Buffer overflow : previous buffer is erased
                readBuffer = data;
            else
                readBuffer = readBuffer + data;


            string line = ReadLine();

            while (line != null)
            {
                // A line has been read
                if (LineReceived != null)
                    LineReceived(line);

                line = ReadLine();
            }
        }

        /// <summary>
        /// Reads a line in the buffer
        /// </summary>
        /// <returns></returns>
        private string ReadLine()
        {
            int newLineIndex = readBuffer.IndexOf('\n');
            if (newLineIndex == -1)
                // The input doesn't contain any newline
                return null;

            // So far we have at least 1 line in the buffer
            string line;
            if (newLineIndex == 0)
                // the input only contains a newline
                line = string.Empty;
            else
                line = readBuffer.Substring(0, newLineIndex);

            if (newLineIndex < readBuffer.Length - 2)
                // There are stills some characters to read in the input
                readBuffer = readBuffer.Substring(newLineIndex + 1);
            else
                readBuffer = string.Empty;

            return line;
        } 
        #endregion

        #region Write
        /// <summary>
        /// Writes a line into the connection.
        /// </summary>
        /// <param name="data"></param>
        public void WriteLine(string data)
        {
            Write(data + "\n");
        }

        /// <summary>
        /// Writes a line into the connection.
        /// </summary>
        /// <param name="line"></param>
        protected abstract void Write(string line);
        #endregion

        #region LineReceived event
        protected void OnLineReceived(string line)
        {
            if (LineReceived != null)
                LineReceived(line);
        }

        public event LineReceivedEventHandler LineReceived; 
        #endregion
    }

    public delegate void LineReceivedEventHandler(string line);


}
